using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;
using System.Xml.Serialization;

namespace my_console;

public static class Extensions
{
  private static readonly XmlSerializerNamespaces defaultNamespace;
  static Extensions()
  {
    // 使用此命名空间，生成干净的xml
    defaultNamespace = new XmlSerializerNamespaces();
    defaultNamespace.Add("", "");
  }

  /// <summary>
  /// 将对象转化为xml
  /// </summary>
  /// <typeparam name="T"></typeparam>
  /// <param name="obj"></param>
  /// <param name="namespaceName"></param>
  /// <returns></returns>
  public static string ToXml<T>(this T obj, bool isDeleteHeader = false)
  {
    using (var sw = new StringWriterWithEncoding(Encoding.UTF8))
    {
      var serializer = new XmlSerializer(typeof(T));
      serializer.Serialize(sw, obj, defaultNamespace);
      var xml = sw.ToString();
      if (isDeleteHeader) // 去掉xml的头部
      {
        xml = Regex.Replace(xml, @"<\?xml.+\?>", "").Trim();
      }
      return xml;
    }
  }
  

  /// <summary>
  /// 转化为RIS对应的患者来源
  /// </summary>
  /// <param name="type"></param>
  /// <returns></returns>
  public static string ToPatientType(this string type)
  {
    switch (type)
    {
      case "1": return "OP";
      case "3": return "IH";
      case "4": return "PE";
      case "2": return "EM";
      case "5": return "INT";
      default: return "OP";
    }
  }

  /// <summary>
  /// 转化为RIS对应的性别编码
  /// </summary>
  /// <param name="type"></param>
  /// <returns></returns>
  public static string ToGender(this string gender)
  {
    switch (gender)
    {
      case "1": return "M";
      case "2": return "F";
      case "0": return "U";
      default: return "M";
    }
  }

  /// <summary>
  /// 将年龄转化为数字，如：21岁
  /// </summary>
  /// <param name="number"></param>
  /// <returns></returns>
  public static string ToAge(this string number) => Regex.Replace(number, @"\D", "");

  /// <summary>
  /// 获得年龄单位
  /// </summary>
  /// <param name="number"></param>
  /// <returns></returns>
  public static string ToAgeUnit(this string number) => Regex.Replace(number, @"\d", "");

  
  public static List<JToken> ToList(this JToken token)
  {
    if (token == null) return new List<JToken>();
    var list = new List<JToken>();
    if (token.GetType() == typeof(JArray))
    {
      foreach (var obj in token)
      {
        list.Add(obj);
      }
    }
    else
    {
      list.Add(token);
    }
    return list;
  }

  public static string Parse(this string val, string type)
  {
    if (string.IsNullOrEmpty(type)) return val;
    switch (type)
    {
      case "PatientType": return val.ToPatientType();
      case "Gender": return val.ToGender();
      case "Age": return val.ToAge();
      case "AgeUnit": return val.ToAgeUnit();
    }
    return val;
  }


  private static Dictionary<Type, PropertyInfo[]> _propertyDic = new Dictionary<Type, PropertyInfo[]>();
  public static PropertyInfo[] GetProperties(this Type type)
  {
    PropertyInfo[] properties;
    if (_propertyDic.ContainsKey(type))
    {
      properties = _propertyDic[type];
    }
    else 
    {
      properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
      _propertyDic.Add(type, properties);
    }
    return properties;
  }
  
  public static void SetValue<T>(this T obj, string key, object val) where T: class, new()
  {
    var properties = obj.GetType().GetProperties();
    var property = properties.FirstOrDefault(a => a.Name == key);
    if (property == null) return;
    property.SetValue(obj, val, null);
    return;
  }
}

/// <summary>
/// 格式化xml时，可设置encoding的类
/// </summary>
public sealed class StringWriterWithEncoding : StringWriter
{
  private readonly Encoding encoding;

  public StringWriterWithEncoding(Encoding encoding)
  {
    this.encoding = encoding;
  }

  public override Encoding Encoding
  {
    get => encoding;
  }
}


